/* 
 * Project: colobok
 * and open the template in the editor.
 * @author: Sviatoslav Mysachenko <svyatoslavik@gmail.com>
 */

/**
 * public methods:
 * getVisibleTilesInQuadTreeList - get list of view tiles (for tile numeration used quad-tree)
 * grig tiles numeration
 * | 2 | 3 |
 * | 0 | 1 |
 */
// http://habrahabr.ru/blogs/google/87894/
// http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/

google.maps.Map.prototype.getVisibleTilesInQuadTreeList = function(zoomLimit){    
    function mercatorconv(from){
        return Math.round((180/Math.PI)*10000000*Math.asin((Math.exp(2*from)-1)/(Math.exp(2*from)+1)))
    }

   function getdatakvnameme(x,y,curzoomkv){
    var xdel=0;
    var ydel=0;
    var ydelm=0;
    var xline=0;
    var yline=0;
    var x1_tochn=-1800000000;
    var x2_tochn=1800000000;
    var y1m=-Math.PI;
    var y2m=Math.PI;
    var n=0;
    var xdel_tochn = 0;
    var z=curzoomkv-1;
    while(z>=0){
        xdel_tochn=(x1_tochn+x2_tochn)/2;
        xdel=Math.round(xdel_tochn);
        ydelm=(y1m+y2m)/2;
        ydel=mercatorconv(ydelm);
        if(x<=xdel){
            x2_tochn=xdel_tochn;
            xline=xline*2
            }else{
            x1_tochn=xdel_tochn;
            xline=xline*2+1
            }
            if(y<=ydel){
            y2m=ydelm;
            yline=yline*2
            }else{
            y1m=ydelm;
            yline=yline*2+1
            }
            z--;
        n++
    }
    var out=new Array();
    out.xline=xline;
    out.yline=yline;
    return out
    }
        function cheakpointme (x,y,xline,yline,curzoomkv){            
            var ydel=0;
            var ydelm=0;
            var x1=-1800000000;
            var x2=1800000000;
            var x1_tochn=-1800000000;
            var x2_tochn=1800000000;
            var y1m=-Math.PI;
            var y2m=Math.PI;
            var y1 = mercatorconv(y1m);
            var y2 = mercatorconv(y2m);
            var n=0;
            var xlinetest=0;
            var ylinetest=0;
            var test=0;
            var xdel_tochn = 0;
            var z=curzoomkv-1;
            while(z>=0){
                xdel_tochn=(x1_tochn+x2_tochn)/2;               
                ydelm = (y1m+y2m)/2;
                ydel = mercatorconv(ydelm);
                test=Math.pow(2,z);
                xlinetest=xline&test;
                ylinetest=yline&test;
                if(xlinetest>0){
                    x1_tochn=xdel_tochn;
                    x1=Math.round(xdel_tochn)+1
                }else{
                    x2_tochn=xdel_tochn;
                    x2=Math.round(xdel_tochn)
                }
                if(ylinetest>0){
                    y1m=ydelm;
                    y1=ydel+1
                }else{
                    y2m=ydelm;
                    y2=ydel
                }
                z--;
                n++
            }
            var out=new Array();
            if((x>=x1)&&(x<=x2)&&(y>=y1)&&(y<=y2)){
                out.res=1
            }else{
                out.res=0
            }
            return out
        }
        function retcode(xline,yline,curzoomkv){
    var xparam=0;
    var yparam=0;
    var test=0;
    var xlinetest=0;
    var ylinetest=0;
    var line='';
    var z=curzoomkv-1;
    var linepart = 0;
    while(z>=0){
        test=Math.pow(2,z);
        xlinetest=xline&test;
        ylinetest=yline&test;
        if(xlinetest>0){
            xparam=1
            }else{
            xparam=0
            }
            if(ylinetest>0){
            yparam=2
            }else{
            yparam=0
            }
            linepart=xparam+yparam;
        line=line+linepart;
        z--
    }
    return line
    }
    
    function getTiles(bounds_sw_lat, bounds_sw_lng, bounds_ne_lat, bounds_ne_lng, zoom){
            var blocshow = [];
            var curzoomkv = zoom;
            var x1point=Math.round(bounds_sw_lng*10000000);
            var y1point=Math.round(bounds_sw_lat*10000000);
            var x2point=Math.round(bounds_ne_lng*10000000);
            var y2point=Math.round(bounds_ne_lat*10000000);
            if(x1point<-1800000000){
                x1point=-1800000000
            }
            if(x2point<-1800000000){
                x2point=-1800000000
            }
            if(x1point>1800000000){
                x1point=1800000000
            }
            if(x2point>1800000000){
                x2point=1800000000
            }
            if(y1point<-850511280){
                y1point=-850511280
            }
            if(y2point<-850511280){
                y2point=-850511280
            }
            if(y1point>850511280){
                y1point=850511280
            }
            if(y2point>850511280){
                y2point=850511280
            }
            var outar=[];
            outar= getdatakvnameme(x1point,y1point,curzoomkv);

            var xline=outar.xline;
            var yline=outar.yline;
            var maks=Math.pow(2,curzoomkv)-1;
            var vlez=0;
            var xsdvig=0;
            var xlinet=xline;
            var ylinet=yline;
            while(vlez!=1){
                outar= cheakpointme(x2point,y1point,xlinet,ylinet,curzoomkv);
                vlez=outar.res;
                xsdvig++;
                xlinet=xlinet+1;
                if(xlinet>maks){
                    xlinet=0
                }
            }
            vlez=0;
            var ysdvig=0;
            xlinet=xline;
            ylinet=yline;
            while(vlez!=1){
                outar=cheakpointme(x1point,y2point,xlinet,ylinet,curzoomkv);
                vlez=outar.res;
                ysdvig++;
                ylinet=ylinet+1;
                if(ylinet>maks){
                    ylinet=0;
                }
            }
            var temp='';          
            var ylinesave=yline;
            var ysdvigsave=ysdvig;
            while(xsdvig>0){
                while(ysdvig>0){
                    temp='0'+retcode(xline,yline,curzoomkv);
                    blocshow.push(temp);                    
                    ysdvig--;
                    yline++;
                    if(yline>maks){
                        yline=0
                    }
                }
                yline=ylinesave;
                ysdvig=ysdvigsave;
                xsdvig--;
                xline++;
                if(xline>maks){
                    xline=0
                }
            }
            return blocshow;
    }
    
    var bounds = this.getBounds();
    var ne = bounds.getNorthEast();
    var sw = bounds.getSouthWest();
    var zoom = this.getZoom();
    if(zoomLimit && (zoomLimit < zoom)) zoom = zoomLimit;
    return getTiles(sw.lat(), sw.lng(), ne.lat(), ne.lng(),zoom);
}